﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace FolderData
{
    public class Camera
    {
        public static readonly int SCREEN_WIDTH = 1280;
        public static readonly int SCREEN_HEIGHT = 720;
        public static readonly float SCREEN_BOUNDARY_WIDTH = 100 * (float)Math.Sqrt(2);
        public static readonly Vector2 ScreenCenter = new Vector2(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);

        private Vector2 _position;
        private Rectangle _viewsize;


        public Vector2 Position
        {
            get { return _position; }
            set { _position = value; }
        }
        public Rectangle Viewsize
        {
            get { return _viewsize; }
            set
            {
                Debug.Assert(value.Width >= SCREEN_WIDTH && value.Height >= SCREEN_HEIGHT, "맵은 적어도 화면보다 커야 합니다.");
                _viewsize = value;
            }
        }


        public Camera(Rectangle mapSize)
        {
            Position = Vector2.Zero;
            Viewsize = mapSize;
        }

        public Camera(Vector2 Position, Rectangle Viewsize)
        {
            this.Position = Position;
            this.Viewsize = Viewsize;
        }

        /// <summary>
        /// 매 프레임 불려 현재 카메라의 위치를 업데이트 한다.
        /// </summary>
        /// <param name="gameTime"></param>
        /// <param name="target">쫓을 타겟. null이면 아무것도 쫓지 않는다.</param>
        public void Update(Vector2? target, GameTime gameTime)
        {
            //기본적으로 target을 쫓게 한다. 
            //후에는 Braid와 같이 Camera action이 가능하도록 한다. 
            //지금 내 생각에는 시간이나 주인공의 위치를 변수로 하는 간단한 일차함수를 
            //내장할 수 있고, 상황에 따라 그것을 바꿔 끼도록 하면 어느정도 될 것 같은데..
            //그리고 그 선을 벗어나면 일정 속도로 카메라가 쫓아오게 하고.
            //뭐 아마 기획이 좀 더 되야지 카메라의 움직임을 잡아줄 수 있을 것이다.
            // 09. 07. 14
            
            //카메라가 대상 물체를 부드럽게 trace하게 하기 위해 Vector2.SmoothStep을 이용.

            if (target.HasValue)
            {
                Position = Vector2.SmoothStep(this.Position, target.Value, 0.1f);
                boundCamera();
            }

            //임시 패치. 타겟과 카메라 사이의 거리에 따라 smoothstep의 amount를 다르게 하여 높은 속도로 움직일 떄
            //카메라가 고양이를 놓치는 일을 없앤다.
            //Vector2 vec = this.Position - target.Value;
            //float amount = vec.Length()/1500;
            //this.Position = Vector2.SmoothStep(this.Position, target.Value, amount);
        }

        public void UpdateCameraToAnchor(Vector2 foldingPos)
        {
            Position = Vector2.SmoothStep(Position, foldingPos - Camera.ScreenCenter + Position, 0.1f);
            boundCamera();
        }

        private void boundCamera()
        {
            if (_position.X < Viewsize.X)
                _position.X = Viewsize.X;
            if (_position.Y < Viewsize.Y)
                _position.Y = Viewsize.Y;
            if (_position.X > Viewsize.X + Viewsize.Width - SCREEN_WIDTH)
                _position.X = Viewsize.X + Viewsize.Width - SCREEN_WIDTH;
            if (_position.Y > Viewsize.Y + Viewsize.Height - SCREEN_HEIGHT)
                _position.Y = Viewsize.Y + Viewsize.Height - SCREEN_HEIGHT;
        }
    }
}
